package robocup.testing;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.LinkedList;

import robocup.component.actions.KickAction;
import robocup.component.actions.TackleAction;
import robocup.component.geometry.Vektor;
import robocup.component.geometry.analysers.PossibleBallsAfterDirectedAcc;
import robocup.component.worldobjects.Ball;
import robocup.component.worldobjects.Player;


/**
 * @author Thomas Karbe
 * 
 * Tests the possible directed balls
 */
public class TestDirected
    extends GraphicalTestFrame {
  
  Player p;
  Ball b;
  PossibleBallsAfterDirectedAcc possBalls;
  Ball b1;
  Ball b2;
  Ball b3;
  Ball b4;
  Ball b5;
  Ball b6;
  Ball b7;
  LinkedList<Vektor> list1;
  LinkedList<Vektor> list2;  
  KickAction kick;
  TackleAction tackle;

  /**
   * 
   */
  public TestDirected() {

    super();
  }

  /**
   * @param d
   */
  public TestDirected(
      Dimension d) {

    super(d);
  }

  /**
   * @param center
   */
  public TestDirected(
      Vektor center) {

    super(center);
  }

  /**
   * @param d
   * @param center
   */
  public TestDirected(
      Dimension d,
      Vektor center) {

    super(d, center);
  }

  /**
   * @param scale
   */
  public TestDirected(
      double scale) {

    super(scale);
  }

  /**
   * @param d
   * @param scale
   */
  public TestDirected(
      Dimension d,
      double scale) {

    super(d, scale);
  }

  /**
   * @param center
   * @param scale
   */
  public TestDirected(
      Vektor center,
      double scale) {

    super(center, scale);
  }

  /**
   * @param d
   * @param center
   * @param scale
   */
  public TestDirected(
      Dimension d,
      Vektor center,
      double scale) {

    super(d, center, scale);
  }

  /** (non-Javadoc)
   * @see robocup.testing.GraphicalTestFrame#nextSituation()
   */
  @Override
  protected void nextSituation() {
    p= rand.getRandomPlayer();
    setCenter(p.getPosition());
    b= rand.getRandomBallInKickable(p);
    System.out.println("\n\nNEXT SIT");
    System.out.println("p: "+p);
    System.out.println("b: "+b);
    list1= new LinkedList<Vektor>();
    list2= new LinkedList<Vektor>();
    if (rand.getRandomBoolean()) {
      double dir= rand.getRandomDouble(-180, 180);
      double pow= 0;
      System.out.println("p KICKs to dir: "+dir);
      possBalls= new PossibleBallsAfterDirectedAcc(p,b,dir);
      System.out.println("possBalls: "+possBalls);
      b1= b.cloned();
      pow= possBalls.getPowerForShotAngleAbs(0);
      list1.add(possBalls.getPointForShotAngleAbs(0));
      System.out.println("needed power for angle 0: "+pow);
      if (pow != Double.MAX_VALUE) {
        kick= new KickAction(pow,dir);
        b1.predictThisAfterAction(p, kick);
        System.out.println("ballpos after kick: "+b1.getPosition()); 
      }
      else {
        b1.setPosition(Vektor.CENTER);
      }
      b2= b.cloned();
      pow= possBalls.getPowerForShotAngleAbs(90);
      list1.add(possBalls.getPointForShotAngleAbs(90));
      System.out.println("needed power for angle 90: "+pow);
      if (pow != Double.MAX_VALUE) {
        kick= new KickAction(pow,dir);
        b2.predictThisAfterAction(p, kick);
        System.out.println("ballpos after kick: "+b2.getPosition()); 
      }
      else {
        b2.setPosition(Vektor.CENTER);
      }
      b3= b.cloned();
      pow= possBalls.getPowerForShotAngleAbs(180);
      list1.add(possBalls.getPointForShotAngleAbs(180));
      System.out.println("needed power for angle 180: "+pow);
      if (pow != Double.MAX_VALUE) {
        kick= new KickAction(pow,dir);
        b3.predictThisAfterAction(p, kick);
        System.out.println("ballpos after kick: "+b3.getPosition()); 
      }
      else {
        b3.setPosition(Vektor.CENTER);
      }
      b4= b.cloned();
      pow= possBalls.getPowerForShotAngleAbs(-90);
      list1.add(possBalls.getPointForShotAngleAbs(-90));
      System.out.println("needed power for angle -90: "+pow);
      if (pow != Double.MAX_VALUE) {
        kick= new KickAction(pow,dir);
        b4.predictThisAfterAction(p, kick);
        System.out.println("ballpos after kick: "+b4.getPosition()); 
      }
      else {
        b4.setPosition(Vektor.CENTER);
      }
      b5= b.cloned();
      double angle= rand.getRandomDouble(-180, 180);
      pow= possBalls.getPowerForShotAngleAbs(angle);
      list2.add(possBalls.getPointForShotAngleAbs(angle));
      System.out.println("needed power for angle "+angle+": "+pow);
      if (pow != Double.MAX_VALUE) {
        kick= new KickAction(pow,dir);
        b5.predictThisAfterAction(p, kick);
        System.out.println("ballpos after kick: "+b5.getPosition()); 
      }
      else {
        b5.setPosition(Vektor.CENTER);
      }
      b6= b.cloned();
      angle= rand.getRandomDouble(-180, 180);
      pow= possBalls.getPowerForShotAngleAbs(angle);
      list2.add(possBalls.getPointForShotAngleAbs(angle));
      System.out.println("needed power for angle "+angle+": "+pow);
      if (pow != Double.MAX_VALUE) {
        kick= new KickAction(pow,dir);
        b6.predictThisAfterAction(p, kick);
        System.out.println("ballpos after kick: "+b6.getPosition()); 
      }
      else {
        b6.setPosition(Vektor.CENTER);
      }
      b7= b.cloned();
      angle= rand.getRandomDouble(-180, 180);
      list2.add(possBalls.getPointForShotAngleAbs(angle));
      pow= possBalls.getPowerForShotAngleAbs(angle);
      System.out.println("needed power for angle "+angle+": "+pow);
      if (pow != Double.MAX_VALUE) {
        kick= new KickAction(pow,dir);
        b7.predictThisAfterAction(p, kick);
        System.out.println("ballpos after kick: "+b7.getPosition()); 
      }
      else {
        b7.setPosition(Vektor.CENTER);
      }
    }
    else {
      System.out.println("p TACKLEs: ");
      possBalls= new PossibleBallsAfterDirectedAcc(p,b);
      System.out.println("possBalls: "+possBalls);
      double pow= 0;
      b1= b.cloned();
      pow= possBalls.getPowerForShotAngleAbs(0);
      list1.add(possBalls.getPointForShotAngleAbs(0));
      System.out.println("needed power for angle 0: "+pow);
      if (pow != Double.MAX_VALUE) {
        tackle= new TackleAction(pow);
        b1.predictThisAfterAction(p, tackle);
        System.out.println("ballpos after tackle: "+b1.getPosition()); 
      }
      else {
        b1.setPosition(Vektor.CENTER);
        b1.setSpeed(Vektor.CENTER);
      }
      b2= b.cloned();
      pow= possBalls.getPowerForShotAngleAbs(90);
      list1.add(possBalls.getPointForShotAngleAbs(90));
      System.out.println("needed power for angle 90: "+pow);
      if (pow != Double.MAX_VALUE) {
        tackle= new TackleAction(pow);
        b2.predictThisAfterAction(p, tackle);
        System.out.println("ballpos after tackle: "+b2.getPosition()); 
      }
      else {
        b2.setPosition(Vektor.CENTER);
        b2.setSpeed(Vektor.CENTER);
      }
      b3= b.cloned();
      pow= possBalls.getPowerForShotAngleAbs(180);
      list1.add(possBalls.getPointForShotAngleAbs(180));
      System.out.println("needed power for angle 180: "+pow);
      if (pow != Double.MAX_VALUE) {
        tackle= new TackleAction(pow);
        b3.predictThisAfterAction(p, tackle);
        System.out.println("ballpos after tackle: "+b3.getPosition()); 
      }
      else {
        b3.setPosition(Vektor.CENTER);
        b3.setSpeed(Vektor.CENTER);
      }
      b4= b.cloned();
      pow= possBalls.getPowerForShotAngleAbs(-90);
      list1.add(possBalls.getPointForShotAngleAbs(-90));
      System.out.println("needed power for angle -90: "+pow);
      if (pow != Double.MAX_VALUE) {
        tackle= new TackleAction(pow);
        b4.predictThisAfterAction(p, tackle);
        System.out.println("ballpos after tackle: "+b4.getPosition()); 
      }
      else {
        b4.setPosition(Vektor.CENTER);
        b4.setSpeed(Vektor.CENTER);
      }
      double angle= rand.getRandomDouble(-180, 180);
      b5= b.cloned();
      pow= possBalls.getPowerForShotAngleAbs(angle);
      list2.add(possBalls.getPointForShotAngleAbs(angle));
      System.out.println("needed power for angle +"+angle+": "+pow);
      if (pow != Double.MAX_VALUE) {
        tackle= new TackleAction(pow);
        b5.predictThisAfterAction(p, tackle);
        System.out.println("ballpos after tackle: "+b5.getPosition()); 
      }
      else {
        b5.setPosition(Vektor.CENTER);
        b5.setSpeed(Vektor.CENTER);
      }
      angle= rand.getRandomDouble(-180, 180);
      b6= b.cloned();
      pow= possBalls.getPowerForShotAngleAbs(angle);
      list2.add(possBalls.getPointForShotAngleAbs(angle));
      System.out.println("needed power for angle +"+angle+": "+pow);
      if (pow != Double.MAX_VALUE) {
        tackle= new TackleAction(pow);
        b6.predictThisAfterAction(p, tackle);
        System.out.println("ballpos after tackle: "+b6.getPosition()); 
      }
      else {
        b6.setPosition(Vektor.CENTER);
        b6.setSpeed(Vektor.CENTER);
      }
      angle= rand.getRandomDouble(-180, 180);
      b7= b.cloned();
      pow= possBalls.getPowerForShotAngleAbs(angle);
      list2.add(possBalls.getPointForShotAngleAbs(angle));
      System.out.println("needed power for angle +"+angle+": "+pow);
      if (pow != Double.MAX_VALUE) {
        tackle= new TackleAction(pow);
        b7.predictThisAfterAction(p, tackle);
        System.out.println("ballpos after tackle: "+b7.getPosition()); 
      }
      else {
        b7.setPosition(Vektor.CENTER);
        b7.setSpeed(Vektor.CENTER);
      }
    }
    
  }

  /** (non-Javadoc)
   * @see robocup.testing.GraphicalTestFrame#nextCycle()
   */
  @Override
  protected void nextCycle() {
    list1.clear();
    list2.clear();
    possBalls.extrapolateThis();
    if (b1.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      b1.extrapolate(1);
    }
    list1.add(possBalls.getPointForShotAngleAbs(0));
    if (b2.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      b2.extrapolate(1);
    }
    list1.add(possBalls.getPointForShotAngleAbs(90));
    if (b3.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      b3.extrapolate(1);
    }
    list1.add(possBalls.getPointForShotAngleAbs(180));
    if (b4.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      b4.extrapolate(1);
    }
    list1.add(possBalls.getPointForShotAngleAbs(-90));
    if (b5.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      b5.extrapolate(1);      
    }
    if (b6.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      b6.extrapolate(1);
    }
    if (b7.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      b7.extrapolate(1);
    }
  }

  /** (non-Javadoc)
   * @see robocup.testing.GraphicalTestFrame#paintSituation(java.awt.Graphics)
   */
  @Override
  protected void paintSituation(Graphics g) {
    g.setColor(Color.RED);
    drawMovement(g, b);
    drawMovement(g, p);
    drawKickable(g, p);
    g.setColor(Color.YELLOW);
    draw(g, p);
    g.setColor(Color.BLACK);
    draw(g, b);
    g.setColor(Color.BLUE);
    draw(g, possBalls);
    g.setColor(Color.green);
    if (b1.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      draw(g, b1);
      drawMovement(g, b1);
      g.drawString(Double.toString(b.getAngleTo(b1))+" "+list1.get(0), 50, 50);
      if (list1.get(0) != null) {
        draw(g,list1.get(0));
      }
    }
    else {
      g.drawString("0 degree not possible", 50, 50);
    }
    if (b2.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      draw(g, b2);
      drawMovement(g, b2);
      g.drawString(Double.toString(b.getAngleTo(b2))+" "+list1.get(1), 50, 80);
      if (list1.get(1) != null) {
        draw(g,list1.get(1));
      }
    }
    else {
      g.drawString("90 degree not possible", 50, 80);
    }
    if (b3.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      draw(g, b3);
      drawMovement(g, b3);
      g.drawString(Double.toString(b.getAngleTo(b3))+" "+list1.get(2), 50, 110);
      if (list1.get(2) != null) {
        draw(g,list1.get(2));
      }
    }
    else {
      g.drawString("180 degree not possible", 50, 110);
    }
    if (b4.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      draw(g, b4);
      drawMovement(g, b4);
      g.drawString(Double.toString(b.getAngleTo(b4))+" "+list1.get(3), 50, 140);
      if (list1.get(3) != null) {
        draw(g,list1.get(3));
      }
    }
    else {
      g.drawString("-90 degree not possible", 50, 140);
    }
    g.setColor(Color.orange);
    if (b5.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      draw(g, b5);
      drawMovement(g, b5);
      g.drawString(Double.toString(b.getAngleTo(b5)), 50, 170);
    }
    else {
      g.drawString("b5 not possible", 50, 170);
    }
    if (b6.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      draw(g, b6);
      drawMovement(g, b6);
      g.drawString(Double.toString(b.getAngleTo(b6)), 50, 200);
    }
    else {
      g.drawString("b6 degree not possible", 50, 200);
    }
    if (b7.getPosition().getDistance(Vektor.CENTER) > 0.1) {
      draw(g, b7);
      drawMovement(g, b7);
      g.drawString(Double.toString(b.getAngleTo(b7)), 50, 230);
    }
    else {
      g.drawString("b7 degree not possible", 50, 230);
    }
    
  }

  /**
   * @param args
   */
  public static void main(String[] args) {
    new TestDirected();
  }

}
